/*************************************************************************
 *
 * funkce logovani a vyssiho pristupu do dataflash pameti
 * 
 * (c) Ales Povalac, alpov@alpov.net, http://www.alpov.net/
 * 
 *************************************************************************
 *
 * $Id: log.c 88 2006-11-08 07:24:42Z alpov $
 * 
 *************************************************************************/         

#include <stdint.h>
#include <string.h>
#include "../avrx/avrx.h"
#include "../avrx/AvrXFifo.h"
#include <util/delay.h>
#include "log.h"
#include "dataflash.h"
#include "data.h"

Mutex DataFlashMutex;
static unsigned int page = 0;


/*************************************************************************
 * inicializace logovani - dataflash
 *************************************************************************/ 
void InitLog(void)
{
    _delay_ms(20); // startup flashky
    DF_SPI_init();
    AvrXSetSemaphore(&DataFlashMutex);
}


/*************************************************************************
 * smazani cele dataflash
 *************************************************************************/ 
void LogEraseAll(void)
{
    AvrXWaitSemaphore(&DataFlashMutex);
    
    for (int i = 0; i < Pages; i += 8)
        Block_Erase(i);
    
    page = 0;
    Buffer_Fill(Buf1Write, 0xff);
    
    AvrXSetSemaphore(&DataFlashMutex);
}


/*************************************************************************
 * obecna funkce logovani
 *************************************************************************/ 
void LogWrite(char *data, unsigned char length)
{
    unsigned int buf_pos;
    unsigned char c;
    
    AvrXWaitSemaphore(&DataFlashMutex);
    
    Buffer_Read(Buf1Read, DF_BUF_POS, sizeof(buf_pos), (char*)(&buf_pos));
    Buffer_Read(Buf1Read, buf_pos, sizeof(c), &c);
    
    if (c != 0x00) {
        // pozice v bufferu neni platna, smazat buffer a od zacatku
        Buffer_Fill(Buf1Write, 0x00);
        buf_pos = 0;
    }
    
    if ((buf_pos + length) >= PageSizeNorm) {
        // pokud je buffer plny, uzavrit stranku, smazat nasledujici a zapsat

        // nejdriv zkontrolovat, zda je zapisovana stranka prazdna, jinak vyhledavani
        Buffer_Fill(Buf2Write, 0xff);
        if (Page_Buffer_Compare(FlashToBuf2Compare, page)) {
            // neni same 0xff - page neplatny, jde se prohledavat
            page = 0;
            while ((Page_Buffer_Compare(FlashToBuf2Compare, page)) && (page < Pages))
                page++;
            
            // nenalezena prazdna stranka - od zacatku dataflash
            if (page == Pages) {
                page = 0;
                Page_Erase(0);  // sem budeme zapisovat, dalsi stranka se smaze v nasledujicim kroku
            }
        }
        
        // 'page' inicializovano, muzeme smazat nasledujici, zapsat a vycistit buffer
        Page_Erase(page + 1);
        Buffer_To_Page(Buf1ToFlash, page);
        page++;
        Buffer_Fill(Buf1Write, 0x00);
        buf_pos = 0;                
    }
    
    // zapsat do bufferu
    Buffer_Write(Buf1Write, buf_pos, length, data);
    
    buf_pos += length;
    Buffer_Write(Buf1Write, DF_BUF_POS, sizeof(buf_pos), (char*)(&buf_pos));
//  Buffer_Write(Buf1Write, DF_RTC_POS, sizeof(rwdata.now), (char*)(&rwdata.now));
    
    AvrXSetSemaphore(&DataFlashMutex);
}


/*************************************************************************
 * logovani teplot
 *************************************************************************/ 
void LogWriteTemperature(void)
{
    struct {
        unsigned long now;
        unsigned char sensor_count;
        signed int temperature[SENSOR_MAX_COUNT];
    } s;
    unsigned char length;
    
    s.now = rwdata.now;
    s.sensor_count = AvrXReadEEProm(&eedata.sensor_count);
    memcpy(&s.temperature, &stdata.temperature, sizeof(s.temperature));
        
    length = sizeof(s.now) + sizeof(s.sensor_count) + s.sensor_count * sizeof(s.temperature[0]);
    LogWrite((char*)(&s), length);
}

